'''
This file is part of DopplerShift.

    DopplerShift is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DopplerShift is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DopplerShift.  If not, see <http://www.gnu.org/licenses/>.
'''

from lxml import etree
from twisted.python import log
import traceback
from twisted.web.server import NOT_DONE_YET
from dopplershift.collector.http import REQUEST_METHOD_GET, REQUEST_METHOD_POST, REQUEST_METHOD_NONE
from dopplershift.core.containers.mediator import DSMediatorSingleton, getMediator
from dopplershift.collector.handler.calls import RemoteCall
from dopplershift.collector.exc import Http500, Http404
import logging
from dopplershift.core.events import DSEventManager
from dopplershift.collector.handler.render import Render
logger = logging.getLogger(__name__)

class RequestHandler(DSEventManager):
    render = Render
    _method = REQUEST_METHOD_NONE
    _condition = None
    _auth_user = None
    def __init__(self, request, request_params,  xml_route, method=REQUEST_METHOD_NONE):
        self._route = xml_route
        self._params = request_params
        self._app_responses = {}
        mediator = getMediator()
        self._calls_cnt = 0
        
        self._id = mediator.get('CollectorHandlers').set(self, 10) 
        self._request = mediator.get('CollectorRequests').set(request, 10)
        DSEventManager.__init__(self, [
                                       'AuthResponse',
                                       'RemoteServiceAnswer',
                                       'CallsFinished',
                                       'StartRendering'
                                       ]
        )
        
         
        self._render = self.render(self._id, self._request)
        self.sign("CallsFinished", self._render.callsProcessing)
        self.sign("StartRendering", self.startRendering)
        self.sign("RemoteServiceAnswer", self.remoteServiceAnswer)
        self.sign("AuthResponse", self._render.authResponse)
        self.sign("AuthResponse", self.authResponse)
    def startRendering(self, arg):
        mediator = getMediator()
        mediator.get('CollectorRequests').remove(self._request)
        mediator.get('CollectorHandlers').remove(self._id)
    def remoteServiceAnswer(self, answer ):
        '''
        Event handler for catching result from application services
        '''
        self._app_responses[answer.id] = answer
        if len(self._app_responses) == self._calls_cnt:
            self.signal('CallsFinished', {"responses": self._app_responses, "matched_params": self._params})
    def _prepareHttpArgs(self, args):
        result = []
        for el in args:
            cnt = len(args[el])
            if cnt > 1:
                for val in args[el]:
                    result.append((el, val))
            elif cnt > 0:
                result.append((el, args[el][0]))
        return result
    def _prepareHttpHeaders(self, headers):
        result = {}
        for el in headers.getAllRawHeaders():
            result[el[0]] = el[1][0]
        return result
    def authResponse(self, answer):
        self._auth_user = answer
        req = getMediator().get('CollectorRequests').get(self._request)
        req.PARAMS = self._prepareHttpArgs(req.args)
        req.HEADERS = self._prepareHttpHeaders(req.requestHeaders)
        calls_list = self.getCalls(answer)
        self._render.setCondition(self._condition)
        call_list_len = len(calls_list)
        if call_list_len > 0:
            self._calls_cnt = call_list_len
            for el in calls_list:
                el.setRequestId(self._request)
                el.setResponseId(self._id)
                el.call(self._params, self._method)
            return NOT_DONE_YET
        elif self._condition == None:
            logger.warning("Not found URL Dispatcher")
            self._render.renderNotFoundError()
            return
        return self.signal("CallsFinished", {"responses": self._app_responses, "matched_params": None})
    def getCalls(self, authInfo):
        '''
        preparing calls list for remote calling
        '''
        calls_list = []
        self._condition = self._route.findCondition(authInfo, self._method)
        if self._condition:
            for el in self._condition.getCalls():
                calls_list.append(RemoteCall(el, authInfo))
        return calls_list
    def work(self, method):
        '''
        '''
        self._method = method
        mediator = getMediator()
        request = mediator.get('CollectorRequests').get(self._request)
        mediator.get("AuthBackend").isAuth(request.getCookie(mediator.get("CollectorConfig").get('auth_key_name')), self)
        return NOT_DONE_YET
